package test.crane;

import ptolemy.actor.*;
import ptolemy.kernel.*;
import ptolemy.kernel.util.*;
import ptolemy.data.*;
import ptolemy.data.type.*;

//////////////////////////////////////////////////////////////////////////
//// BrakeCondition
/**

@author Ivan Jeukens
@version v 0.1 07/02/2002
*/
public class BrakeCondition extends TypedAtomicActor {

    public BrakeCondition(CompositeEntity container, String name) throws
            IllegalActionException, NameDuplicationException {
        super(container, name);

        shutdown = new TypedIOPort(this, "shutdown", true, false);
        shutdown.setTypeEquals(BaseType.GENERAL);

        emstop = new TypedIOPort(this, "emstop", true, false);
        emstop.setTypeEquals(BaseType.GENERAL);

        trigger = new TypedIOPort(this, "trigger", true, false);
        trigger.setTypeEquals(BaseType.GENERAL);

        emmode = new TypedIOPort(this, "emmode", true, false);
        emmode.setTypeEquals(BaseType.GENERAL);

        vc = new TypedIOPort(this, "vc", true, false);
        vc.setTypeEquals(BaseType.DOUBLE);

        brake = new TypedIOPort(this, "brake", false, true);
        brake.setTypeEquals(BaseType.BOOLEAN);

        new Attribute(this, "_nonStrictMarker");
    }

    public TypedIOPort trigger;
    public TypedIOPort shutdown;
    public TypedIOPort emstop;
    public TypedIOPort emmode;
    public TypedIOPort vc;
    
    public TypedIOPort brake;

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////

    public void pruneDependencies() {
        super.pruneDependencies();
        removeDependency(trigger, brake);
        removeDependency(shutdown, brake);
        removeDependency(emstop, brake);
    }

    public void initialize() throws IllegalActionException  {
        super.initialize();
        _reset();
    }

    public void fire() throws IllegalActionException {
        if(emmode.isKnown()) {
            if(emmode.hasToken(0)) {
                emmode.get(0);
                _inEmMode = true;
            }
        }

        if(_state == RUNNING) {
            if(vc.isKnown() && !brake.isKnown()) {
            //if(vc.isKnown()) {
                if(vc.hasToken(0)) {
                    _vc = ((DoubleToken)vc.get(0)).doubleValue();

                    if(Math.abs(_vc) < 0.01) {
                        _count++;
                    }
                    else {
                        _count = 0;
                    }

                    if(_inEmMode) {
                        if(_count == 7500) {
                            brake.broadcast(new BooleanToken(true));
                            System.out.println("VC Brake condition reached!");
                            _count = 0;
                        }
                    }
                    else {
                        if(_count == 2500) {
                            brake.broadcast(new BooleanToken(true));
                            System.out.println("VC Brake condition reached!");
                            _count = 0;
                        }
                    }
                }
            }
        }
        if(vc.isKnown() && emmode.isKnown() && !brake.isKnown()) {
            brake.broadcastClear();
        }
    }

    public boolean postfire() throws IllegalActionException {

        switch(_state) {
            case READY: {
                if(trigger.isKnown()) {
                    if(trigger.hasToken(0)) {
                        trigger.get(0);
                        _state = RUNNING;
                    }
                }
            } break;

            case RUNNING: {
                if(shutdown.isKnown()) {
                    if(shutdown.hasToken(0)) {
                        shutdown.get(0);
                        _reset();
                        break;
                    }
                }

                if(emstop.isKnown()) {
                    if(emstop.hasToken(0)) {
                        emstop.get(0);
                        _reset();
                    }
                }
            }
        }
        return true;
    }

    ///////////////////////////////////////////////////////////////////
    ////                        private methods                    ////

    private void _reset() {
        _state = READY;
        _inEmMode = false;
        _count = 0;
    }

    ///////////////////////////////////////////////////////////////////
    ////                      private variables                    ////

    private int _state;
    private boolean _inEmMode;
    private double _vc;
    private int _count;

    private static final int READY = 1;
    private static final int RUNNING = 2;
}
